'use strict'
var http = require('http');
var fs = require('fs');
function parseBodyHeaders(data) {
    let headers = {}
    // \r\ncontent-type:multipart/form-data; boundary=-----34294329
    let dsplit = data.split('\r\n').filter(p => p.length >0)
    
    let ind;
    let k;
    for(let d of dsplit){
        ind = d.indexOf(':');

        if(ind<=0) continue;

        k=d.substring(0,ind).toLowerCase();

        headers[k] = d.substring(ind+1).trim();

    }


    let cpd = headers['content-disposition'];

    // 按照;分割成数组，第一个元素form-data去掉
    let cList = cpd.split('; ').slice(1);
    let name,filename;
    for (let a of cList) {
        ind = a.indexOf('filename="')
        if(ind >= 0){
            filename = a.substring(ind+10, a.length-1)
        }else{
            name = a.substring(6,a.length - 1)
        }
    }
    return {
        headers,
        name,
        filename
    }
}
/**
 * 这部分是注释，vs code中会添加对参数的描述
 * @param {Buffer} bodyData 原始的Body数据
 * @param {Object} reqHeader req.headers
 */

function parseBody(bodyData,reqHeader) {

    // content-type:multipart/form-data; boundary=-----34294329
    let ctype = reqHeader['content-type'];
    // 拿到分界线boundary
    let bdy = ctype.substring(ctype.indexOf('=')+1);//拿到boundary的值开始位置
    // body在构造数据会在boundary前面再加两个减号
    // 数据的结尾会在上面的那个后面再加两个减号
    // 数据中用于分割文件的分割线
    // bdy = `--${bdy}\r\n`;
    let crlf_bdy = `\r\n--${bdy}`;
    // 从偏移crlf_bdy的长度的位置开始查找下一个分界线的位置
    let data_end_index = bodyData.indexOf(crlf_bdy,crlf_bdy.length);

    // body消息数据中header部分的最后索引
    let header_end_index = bodyData.indexOf('\r\n\r\n',bdy.length);

    let header_data = bodyData.toString('utf-8',crlf_bdy.length,header_end_index);
    // 解析body数据中的消息头
    let hd = parseBodyHeaders(header_data);
    
    let fileinfo = {
        start:header_end_index+4,
        end:data_end_index,
    }
    fileinfo.length = fileinfo.end - fileinfo.start;

    return{
        name:hd.name,
        filename:hd.filename,
        headers:hd.headers,
        start:fileinfo.start,
        end:fileinfo.end,
        length:fileinfo.length
    }
}

let routerTable = {
    GET:{
        '/upload':async (req,res)=>{
            let stm = fs.createReadStream('./upload.html');
            stm.pipe(res);
            stm.on('end',()=>{
                res.end();
            })
        },
    },
    POST:{
        '/upload':async (req,res)=>{//表单使用了POST方式提交了数据，所以采用这种处理

            // console.log(req.headers);
            
            let bufferList=[];
            let totalLength = 0;
            req.on('data',(chunk)=>{
                totalLength = chunk.length;
                bufferList.push(chunk);
            })

            let bodyData = null;

            req.on('end',()=>{
                bodyData = Buffer.concat(bufferList,totalLength);
                bufferList=[];
                
                // 解析单文件数据
                let body = parseBody(bodyData,req.headers);
                console.log(body);

                res.setHeader('content-type',
                            'text/plain;charset=utf-8');
                res.end(bodyData);
            })
        }
    }
}

let serv = http.createServer();
serv.on('request',(req,res)=>{
    let rm = routerTable[req.method];

    // 利用参数与路径间的?来切分字符串
    let usplist = req.url.split("?");
    let pathname = usplist[0];
    let querystring = usplist[1] ||'';
    // 这里如果上传了参数就会导致无法访问，所以要用上面对url进行切分来解决这个问题
    if(!rm || !rm[pathname]){
        res.statusCode = 404;
        res.end("page not found")
        return
    }
    rm[pathname](req,res)
})
serv.listen(3456);

